package com.gitee.wsl.reflect.func.library

import com.gitee.wsl.reflect.func.Function

val Library.Companion.defaultRegister: LibraryRegistrant get() = LibraryRegistrant.default

/**
 * Component that is responsible for registering libraries in a pipeline's [Context],
 * in order to be looked up later.
 * @param context context to push libraries to
 */
class LibraryRegistrant(
    private val context: MutableSet<Library> = mutableSetOf()
) {

    private var _funCacheSet:Sequence<Function<*>>? = null

    /**
     * Registers a new single library, allowing it to be looked up by functions
     * and its [Library.onLoad] action is executed.
     * @param library library to register
     */
    fun register(library: Library) {
        _funCacheSet = null
        context += library
        library.onLoad?.invoke()
    }

    /**
     * Registers a new set of libraries, allowing them to be looked up by functions.
     * and their [Library.onLoad] action is executed.
     * @param libraries libraries to register
     */
    fun registerAll(libraries: Collection<Library>) {
        libraries.forEach(::register)
    }

    fun getFunctionByName(name: String): Function<*>?{
        if(_funCacheSet == null)
            buildCache()
        return _funCacheSet?.find { it.name == name }
    }

    private fun buildCache(){
        _funCacheSet = context.asSequence().flatMap { it.functions }
    }

    companion object{
        val default = LibraryRegistrant()
    }
}